package org.game.manager;

import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.bean.StoreGrid;
import org.bean.StoreInfo;
import org.bean.StoreInfo.ServerLimit;
import org.cfg.CommodityCfg;
import org.cfg.StoreCfg;
import org.cfg.cache.CommodityCfgCache;
import org.cfg.cache.StoreCfgCache;
import org.constant.EventConditionKey;
import org.constant.EventConditionType;
import org.constant.EventType;
import org.constant.StoreConstant;
import org.error.GameErrorCode;
import org.game.cache.OnlinePlayerCache;
import org.game.cache.ServerLimitCommodityBuyRecordCache;
import org.game.db.bean.CommodityBuyRecord;
import org.game.db.bean.Player;
import org.game.db.bean.PlayerData;
import org.game.db.bean.PlayerStore;
import org.game.db.cache.CommodityBuyRecordCache;
import org.game.db.cache.PlayerStoreCache;
import org.game.log.builder.LogDsp;
import org.game.log.dsp.GoodsDsp;
import org.game.module.storebo.BuySuccessHandler;
import org.game.module.storebo.StoreBO;
import org.game.msgBuilder.StoreMsgBuilder;
import org.game.plugin.event.GameEvent;
import org.game.plugin.event.GameEventPlugin;
import org.game.protobuf.s2c.S2CItemMsg;
import org.game.protobuf.s2c.S2CShareMsg.ChangeType;
import org.game.protobuf.s2c.S2CStoreMsg.CommodityBuyLogs;
import org.game.protobuf.s2c.S2CStoreMsg.DynamicCommodity;
import org.game.protobuf.s2c.S2CStoreMsg.RespDynamicCommodity;
import org.utils.TimeUtil;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.sojoys.artifact.constant.DataModelKeyEnum;
import com.sojoys.artifact.factory.message.IMessage;
import com.sojoys.artifact.manager.JsonManager;
import com.sojoys.artifact.manager.MessageManager;
import com.sojoys.artifact.tools.ToolDate;
import com.sojoys.artifact.tools.ToolError;
import com.sojoys.artifact.tools.ToolMap;
import com.sojoys.artifact.tools.ToolRandom;
import com.xiaoleilu.hutool.collection.CollUtil;
import com.xiaoleilu.hutool.date.DateUnit;
import com.xiaoleilu.hutool.date.DateUtil;

/**
 * @author : DengYing
 * @CreateDate : 2017年9月11日 下午4:58:39
 * @Description ：商城管理器
 */
@SuppressWarnings("unchecked")
public class StoreManager {
	private StoreManager() {
	}

	private static StoreManager ME = new StoreManager();

	public static StoreManager me() {
		return ME;
	}
	
	
	/**
	 * 购买商品
	 * @param player
	 * @param cid
	 * @param num
	 * @param handler 购买成功处理
	 */
	public void buy(Player player, int cid, int num,BuySuccessHandler handler) {
		CommodityCfg commodityCfg = CommodityCfgCache.me().getById(cid);

		ToolError.isAndTrue(GameErrorCode.NOT_FOND_COMMODITY, "商品信息不存在", commodityCfg == null);

		StoreCfg storeCfg = StoreCfgCache.me().getById(commodityCfg.getStoreId());
		
		ToolError.isAndTrue(GameErrorCode.STORE_NOT_OPEN, "商城未开启", !StoreManager.me().checkStoreOpen(player,storeCfg));
		
		ToolError.isAndTrue(GameErrorCode.COMMODITY_NOT_OPEN, "商品未开启", !StoreManager.me().checkCommodityOpen(player,commodityCfg));
		
		ToolError.isAndTrue(GameErrorCode.BUY_MAX_LIMIT, "已达购买上限", !StoreManager.me().checkBuyRecord(player, cid, num));

		// 累计扣除
		int[] priceTypes = commodityCfg.getPriceType();
		int[] priceVals = commodityCfg.getPriceVal();

		Map<Integer, Integer> costMap = Maps.newHashMap();
		for (int i = 0; i < priceVals.length; i++) {
			int costNum = ToolMap.getInt(priceTypes[i], costMap) + (priceVals[i] * num);
			costMap.put(priceTypes[i], costNum);
		}

		// 累计获得
//		Map<Integer, Integer> goodsMap = commodityCfg.getGoods();
//		for (Entry<Integer, Integer> goods : goodsMap.entrySet()) {
//			goods.setValue(goods.getValue() * num);
//		}
		
		Map<Integer,Integer> goodsNum = Maps.newHashMap();
		// 累计获得
		Map<Integer, Integer> goodsMap = commodityCfg.getGoods();
		for (Entry<Integer, Integer> goods : goodsMap.entrySet()) {
			goodsNum.put(goods.getKey(),goods.getValue()*num);
		}


		LogDsp log = LogDsp.newBuilder(GoodsDsp.STORE_BUY).addAttr("cid", cid).addAttr("num", num);
		LogDsp cloneLog = log.clone();
		// 扣除物品
		ItemManager.costGoodsByCid(player, costMap, log, S2CItemMsg.ItemList.newBuilder());

		// 发货
		handler.deliverGoods(player, goodsNum,cloneLog);
		
		// 添加个人购买记录
		StoreManager.me().addBuyRecordAndPush(player, commodityCfg , num);
		
		// 购买事件
		Map<String, Object> in = Maps.newHashMap();
		in.put(EventConditionKey.CONDITION_TYPE, EventConditionType.STORE_BUY);
		in.put(EventConditionKey.COMMODITY_CID, cid);
		in.put(EventConditionKey.STORE_CID, commodityCfg.getStoreId());
		GameEvent event = new GameEvent(player, EventType.OTHER_EVENT, in);
		GameEventPlugin.syncSubmit(event);
	}

	
	/**
     * 自动刷新商店
     *
     * @param players     玩家列表
     * @param todayMinute 当日分钟数
     */
    private void autoRefreshShop(Map<StoreCfg, Boolean> stores,Map<CommodityCfg, Boolean> commoditys) {
    	Collection<Player> players = OnlinePlayerCache.getAll();
    	players.forEach(player -> {
    		// 受影响的购买记录
    		Set<CommodityCfg> affectCommoditys = Sets.newHashSet();
    		// 受影响的商城信息
    		List<StoreCfg> affectStores = Lists.newArrayList();
    		
    		
    		// 刷新商城
    		stores.forEach((cfg,isNewDay)->{

    			PlayerStore store = PlayerStoreCache.me().getPlayerStoreCacheProxy().getStoreByCid(player.getId(),cfg.getId());
                if (store == null){
                    return;
                }
                
                affectCommoditys.addAll(StoreManager.me().resetStore(player, cfg, isNewDay, true));    
	    		
	    		// 取得具体某个商店
                store.setLastAutoRefreshTime(new Date());
                if (isNewDay) {
                    store.setTodayRefreshCount(0);
                }
                store.update();
                if (!affectStores.contains(cfg)) {
                	affectStores.add(cfg);	
				}
    		});
    		
    		// 刷新商品
    		commoditys.forEach((cfg,isNewDay)->{
				// 清除商品的购买信息
				if (clearCommodityBuyRecord(player, cfg, isNewDay,true)) {
					affectCommoditys.add(cfg);
				}
				
    			StoreCfg storeCfg = StoreCfgCache.me().getById(cfg.getStoreId());
    			if (!affectStores.contains(storeCfg)) {
                	affectStores.add(storeCfg);	
				}
    		});
    		
    		if (affectStores.size() > 0){
    			// 商品信息更新
                player.getPlayerProxy().sendMsg(StoreBO.refreshStore,StoreMsgBuilder.createRefreshStoreMsg(player, affectStores));
            }
    		
    		if (!affectCommoditys.isEmpty()) {
            	// 购买记录更新
                CommodityBuyLogs commodityBuyLogs = StoreMsgBuilder.createBuyRecordInfo(player, affectCommoditys);
                player.getPlayerProxy().sendMsg(MessageManager.me().create(StoreBO.getCommodityBuyLog, commodityBuyLogs.toByteArray()));
			}
    	});
    }

	/**
	 * 随机商品信息
	 *
	 * @param shopType
	 * @return
	 */
	public List<CommodityCfg> randomCommodity(Player player,int shopType) {
		List<CommodityCfg> commoditys = Lists.newArrayList();
		// 取得商店的所有格子信息
		Map<Integer, StoreGrid> shopCommodity = CommodityCfgCache.me().getMaping().row(shopType);

		for (Entry<Integer, StoreGrid> entry : shopCommodity.entrySet()) {
			StoreGrid shopGrid = entry.getValue();
			List<CommodityCfg> cfgs = shopGrid.getCfgs();
			// 筛选
			List<CommodityCfg> reach = Lists.newArrayList();
			int totalWeight = 0;
			for (CommodityCfg commodityCfg : cfgs) {
				if(checkCommodityOpen(player, commodityCfg)){
					reach.add(commodityCfg);
					totalWeight+=commodityCfg.getWeight();
				}
			}
			
			int randomWeight = ToolRandom.randInt(0, totalWeight);
			totalWeight = 0;
			for (CommodityCfg commodityCfg : reach) {
				totalWeight += commodityCfg.getWeight();
				if (totalWeight >= randomWeight) {
					commoditys.add(commodityCfg);
					break;
				}
			}
		}
		return commoditys;
	}

	// 取得玩家商城商品信息
	public List<CommodityCfg> getPlayerShopCommodity(int storeCid, Player player) {
		PlayerStore store = PlayerStoreCache.me().getPlayerStoreCacheProxy().getStoreByCid(player.getId(), storeCid);
		List<CommodityCfg> commoditys = Lists.newArrayList();

		if (store == null) {
			store = new PlayerStore(0,player.getId(),storeCid, Lists.newArrayList(),0,0,new Date());
			commoditys.addAll(randomCommodity(player,storeCid));

			for (CommodityCfg commodityCfg : commoditys) {
				store.getCommodityIdList().add(commodityCfg.getId());
			}
			store.insert();

		} else {
			List<Integer> removedCfgList = Lists.newArrayList();
			store.getCommodityIdList().forEach( id -> {
				int commodityId = (Integer) id;
				CommodityCfg commodityCfg = CommodityCfgCache.me().getById(commodityId);
				// 商品配置被删除
				if (commodityCfg == null) {
					removedCfgList.add(commodityId);
					return;
				}
				commoditys.add(commodityCfg);
			});
			
			if (CollUtil.isNotEmpty(removedCfgList)) {
				store.getCommodityIdList().removeAll(removedCfgList);
				store.update();
			}
		}
		return commoditys;
	}

	/**
	 * 重置商店
	 * @param player		玩家
	 * @param storeCfg		商店
	 * @param isNextDay		是否跨天
	 * @param auto			是否是系统自动重置
	 * @return
	 */
	public Set<CommodityCfg> resetStore(Player player, StoreCfg storeCfg,boolean isNextDay,boolean auto) {
		// 受影响的商品
		Set<CommodityCfg> affect = Sets.newHashSet();

		switch (storeCfg.getCommoditySupplyType()) {
		case StoreConstant.COMMODITY_SUPPLY_FIXATION_TYPE:
			List<CommodityCfg> cfgs = CommodityCfgCache.me().getByStoreId(storeCfg.getId());
			for (CommodityCfg commodityCfg : cfgs) {
				if (clearCommodityBuyRecord(player, commodityCfg, isNextDay,auto)) {
					affect.add(commodityCfg);
				}
			}
			break;
		case StoreConstant.COMMODITY_SUPPLY_RANDOM_TYPE:
			// 取得玩家商店信息
			PlayerStore store = PlayerStoreCache.me().getPlayerStoreCacheProxy().getStoreByCid(player.getId(),storeCfg.getId());
			if (store == null){
				return affect;
			}
			
			store.getCommodityIdList().forEach(commodityId->{
				CommodityCfg commodityCfg = CommodityCfgCache.me().getById((Integer) commodityId);
				
				// 商品配置信息被删除
				if (commodityCfg == null) {
					return;
				}
				
				// 清除商品的购买信息
				if (clearCommodityBuyRecord(player, commodityCfg, isNextDay,auto)) {
					affect.add(commodityCfg);
				}
			});
			
			// 清空历史商品信息
			store.getCommodityIdList().clear();
			// 重新刷新随机商店商品
			List<CommodityCfg> randoms = randomCommodity(player,storeCfg.getId());
			
			for (CommodityCfg commodityCfg : randoms) {
				store.getCommodityIdList().add(commodityCfg.getId());
			}
			store.update();
			break;
		}

		return affect;
	}

	/**
	 * 登录刷新商店
	 */
	public void loginRefreshShop(Player player) {
		PlayerData playerData = player.getPlayerDatasFkPlayerId();
		
		List<StoreCfg> stores = StoreCfgCache.me().getAll();
		stores.forEach(storeCfg -> {
			PlayerStore store = PlayerStoreCache.me().getPlayerStoreCacheProxy().getStoreByCid(player.getId(),storeCfg.getId());
			if (store == null){
				return;
			}

			// 取得具体某个商店
			long store_last_auto_refresh_time = store.getLastAutoRefreshTime().getTime();

			long serverLastRefreshTime = storeCfg.getLastRefreshDate() ==null ? 0 : storeCfg.getLastRefreshDate().getTime();
			if (store.getLastAutoRefreshTime().getTime() < serverLastRefreshTime) {
                boolean isNextDay = !TimeUtil.isSameDay(store_last_auto_refresh_time, serverLastRefreshTime);
                resetStore(player, storeCfg, isNextDay,true);
                store.setLastAutoRefreshTime(new Date(serverLastRefreshTime));
				if (isNextDay) {
					store.setTodayRefreshCount(0);
				}
                playerData.update();
            }
		});
	}

	/**
	 * 清空当前阶段玩家商城购买记录
	 */
	private boolean clearCommodityBuyRecord(Player player, CommodityCfg commodityCfg,boolean isNextDay,boolean auto) {
		// 不是限购商品不清理
		if (commodityCfg.getLimitType() == StoreConstant.LIMIT_NO_TYPE) {
			return false;
		}
		
		switch (commodityCfg.getLimitType()) {
		case StoreConstant.LIMIT_REFRESH_TIME_TYPE:
			break;
		case StoreConstant.LIMIT_TO_DAY_TYPE:
			if (!isNextDay){
				return false;
			}else {
				break;
			}
		case StoreConstant.LIMIT_TOTAL_TYPE:
			return false;
		case StoreConstant.LIMIT_SERVER_TYPE:	// 全服限购清除自己的购买记录
			if (auto) {
				break;
			}else{
				return false;
			}
		}
		
		CommodityBuyRecord CommodityBuyRecord = CommodityBuyRecordCache.me().getCommodityBuyRecordCacheProxy().getRecordByPlayerIdCommodityId(player.getId(),commodityCfg.getId());
		if (CommodityBuyRecord != null) {
			CommodityBuyRecord.setNowBuyCount(0);
			CommodityBuyRecord.update();
			return true;
		}
		
		return false;
	}

	/**
	 * 添加商品购买信息&推送至客户端
	 */
	public void addBuyRecordAndPush(Player player, CommodityCfg commodityCfg, int num) {
		// 限购物品添加限购记录
		if (commodityCfg.getLimitType() != StoreConstant.LIMIT_NO_TYPE) {
			int pid = player.getId();
			int cid = commodityCfg.getId();
			CommodityBuyRecord commodityBuyRecord = CommodityBuyRecordCache.me().getCommodityBuyRecordCacheProxy().getRecordByPlayerIdCommodityId(pid, cid);
			if (commodityBuyRecord == null) {
				commodityBuyRecord = new CommodityBuyRecord(0L, pid, cid, num, num);
				commodityBuyRecord.insert();
			}else {
				commodityBuyRecord.setNowBuyCount(commodityBuyRecord.getNowBuyCount() + num);
				commodityBuyRecord.setTotalBuyCount(commodityBuyRecord.getTotalBuyCount() + num);
				commodityBuyRecord.update();
			}
			
			// 是否是全服限购商品
			
			if (commodityCfg.getLimitType() == StoreConstant.LIMIT_SERVER_TYPE) {
				// 避免延迟，临时修改及时反馈
				ServerLimitCommodityBuyRecordCache.me().changeNum(commodityCfg.getId(), num);
			}
			// 推送更新
			Set<CommodityCfg> set = new HashSet<>(1);
			set.add(commodityCfg);
			CommodityBuyLogs commodityBuyLogs = StoreMsgBuilder.createBuyRecordInfo(player, set);
			player.getPlayerProxy().sendMsg(MessageManager.me().create(StoreBO.getCommodityBuyLog, commodityBuyLogs.toByteArray()));
		}
	}

	/**
	 * 检查商城是否开启
	 * @param player
	 * @param storeCfg
	 * @return
	 */
	public boolean checkStoreOpen(Player player,StoreCfg storeCfg) {
		
		int openType = storeCfg.getOpenContType();
		switch (openType) {
		case StoreConstant.STORE_PLV_OPEN_CONT:
			if (player.getLevel() < storeCfg.getOpenContVal()) {
				return false;
			}
			break;
		case StoreConstant.STORE_DNU_OPEN_CONT:
			
			break;
		}
		
		Date nowDate = new Date();
		int minute = 0;
		if (storeCfg.getOpenTimeType() == StoreConstant.STORE_OPEN_TIME_TODAY) {
			minute = (int) DateUtil.between(DateUtil.beginOfDay(nowDate),nowDate,DateUnit.MINUTE);
		}else if (storeCfg.getOpenTimeType() == StoreConstant.STORE_OPEN_TIME_WEEK) {
			minute = (int) DateUtil.between(DateUtil.beginOfWeek(nowDate),nowDate,DateUnit.MINUTE);
		}else {
			return true;
		}
		int[] openTime = storeCfg.getOpenTime();
		for (int i = 0; i < openTime.length; i=+2) {
			int b = openTime[i];
			int e = openTime[i+1];
			if (minute >= b && minute <= e) {
				return true;
			}
		}
		return false;
	}
	
	
	
	/**
	 * 检查商品是否开启
	 */
	public boolean checkCommodityOpen(Player player,CommodityCfg commodityCfg) {
		
		int openType = commodityCfg.getOpenContType();
		switch (openType) {
		case StoreConstant.STORE_PLV_OPEN_CONT:
			if (player.getLevel() < commodityCfg.getOpenContVal()) {
				return false;
			}
			break;
		case StoreConstant.STORE_DNU_OPEN_CONT:
			
			break;
		}
		
		Date nowDate = new Date();
		int minute = 0;
		if (commodityCfg.getSellTimeType() == StoreConstant.STORE_OPEN_TIME_TODAY) {
			minute = (int) DateUtil.between(DateUtil.beginOfDay(nowDate),nowDate,DateUnit.MINUTE);
		}else if (commodityCfg.getSellTimeType() == StoreConstant.STORE_OPEN_TIME_TODAY) {
			// 修正周1为每周第一天
			minute = (int) (DateUtil.between(DateUtil.beginOfWeek(nowDate) ,nowDate,DateUnit.MINUTE) + (ToolDate.TIME_DAY / ToolDate.TIME_MINUTE));
		}else {
			return true;
		}
		int[] openTime = commodityCfg.getSellTime();
		for (int i = 0; i < openTime.length; i=+2) {
			int b = openTime[i];
			int e = openTime[i+1];
			if (minute >= b && minute <= e) {
				return true;
			}
		}
		return false;
	}
	
	/**
	 * 检查购买记录
	 */
	public boolean checkBuyRecord(Player player, int commodityId, int num) {
		CommodityCfg commodityCfg = CommodityCfgCache.me().getById(commodityId);
		if (commodityCfg.getLimitType() == StoreConstant.LIMIT_NO_TYPE) {
			return true;
		}

		// 限制购买次数
		if (commodityCfg.getLimitType() != StoreConstant.LIMIT_NO_TYPE) {
			CommodityBuyRecord commodityBuyRecord = CommodityBuyRecordCache.me().getCommodityBuyRecordCacheProxy().getRecordByPlayerIdCommodityId(player.getId(), commodityId);
			
			int nowBuyCount = commodityBuyRecord == null ? 0 : commodityBuyRecord.getNowBuyCount();
			
			int totalBuyCount = commodityBuyRecord == null ? 0 : commodityBuyRecord.getTotalBuyCount();
			
			int alreadyBuyNum = 0;
			
			if (commodityCfg.getLimitType() == StoreConstant.LIMIT_SERVER_TYPE) {
				// 查看个人最大购买数量
				if (alreadyBuyNum + num > commodityCfg.getSerLimit()) {
					return false;
				}
				ServerLimit serverLimit = ServerLimitCommodityBuyRecordCache.me().get(commodityId);
				alreadyBuyNum = serverLimit == null ? 0 : serverLimit.getNowBuyCount();
			}else if (commodityCfg.getLimitType() == StoreConstant.LIMIT_REFRESH_TIME_TYPE  || commodityCfg.getLimitType() == StoreConstant.LIMIT_TO_DAY_TYPE) {
				alreadyBuyNum = nowBuyCount;
			}else if (commodityCfg.getLimitType() == StoreConstant.LIMIT_TOTAL_TYPE) {
				alreadyBuyNum = totalBuyCount;
			}

			// 超过购买限制
			if (alreadyBuyNum + num > commodityCfg.getLimitVal()) {
				return false;
			}

		}
		return true;
	}

//	/**
//	 * 获取下次刷新时间
//	 */
//	public int getNextRefreshTime(StoreCfg storeCfg) {
//		if (storeCfg.getAutoRefreshTime() == null || storeCfg.getAutoRefreshTime().length == 0)
//			return 0;
//
//		int todaySecond = (int) (TimeUtil.getTodayTimeMillis() / 1000);
//		int i = 0;
//		for (; i < storeCfg.getAutoRefreshTime().length; i++) {
//			if (todaySecond < (int) storeCfg.getAutoRefreshTime()[i] * 60)
//				break;
//		}
//		
//		Calendar calendar = Calendar.getInstance();
//		int addMinute = 0;
//		if (i == storeCfg.getAutoRefreshTime().length) {
//			calendar.add(Calendar.DAY_OF_YEAR,1);
//			addMinute = storeCfg.getAutoRefreshTime()[0];
//		} else {
//			addMinute = storeCfg.getAutoRefreshTime()[i];
//		}
//		
//		calendar.set(Calendar.HOUR_OF_DAY, 0);
//		calendar.set(Calendar.MINUTE, addMinute);
//		calendar.set(Calendar.SECOND, 0);
//		calendar.set(Calendar.MILLISECOND, 0);
//		int nextRefreshTime = (int) (calendar.getTimeInMillis() / ToolDate.TIME_SECOND);
//		return nextRefreshTime;
//	}
//
//
//	/**
//	 * 取得服务器上一次应该刷新的时间
//	 * @param storeCfg
//	 * @return
//	 */
//	private long getServerLastRefreshTime(StoreCfg storeCfg) {
//		int[] refreshTimeList = storeCfg.getAutoRefreshTime();
//		if (refreshTimeList == null || refreshTimeList.length == 0)
//			return 0L;
//		int now = TimeUtil.getTodayTimeMinute();
//		int i = 0;
//		for (; i < refreshTimeList.length; i++) {
//			if (now < refreshTimeList[i]) {
//				break;
//			}
//		}
//		Calendar refreshTime = DateUtil.beginOfDay(Calendar.getInstance());
//		if (i == 0) {
//			// 今天第一次刷新时间未到，则上次刷新是昨天最后一次刷新
//			refreshTime.add(Calendar.DAY_OF_YEAR, -1);
//			refreshTime.add(Calendar.MINUTE, refreshTimeList[refreshTimeList.length - 1]);
//		} else {
//			// 最后一次刷新时间是今天某个时间
//			refreshTime.add(Calendar.MINUTE, refreshTimeList[i - 1]);
//		}
//		return refreshTime.getTimeInMillis();
//	}

	
	/**
	 * 同步动态商品
	 */
	public void syncDynamic(List<Map> list,boolean added) {
		RespDynamicCommodity.Builder listBuilder = RespDynamicCommodity.newBuilder();
		DynamicCommodity.Builder builder = null;
		for (Map map : list) {
			builder = DynamicCommodity.newBuilder();
			int id = ToolMap.getInt("id", map);
			CommodityCfg cfg = CommodityCfgCache.me().getById(id);
			if (added) {
				if (cfg!=null) {
					// 商品上架重复
					continue;
				}
				cfg = new CommodityCfg();
				cfg.createForMap(DataModelKeyEnum.SOURCE, map);
				CommodityCfgCache.me().addCache(cfg);
				builder.setCt(ChangeType.ADD);
			}else {
				if (!cfg.isDynamic()) {
					// 不是动态商品不能下架
					continue;
				}
				CommodityCfgCache.me().removeCache(cfg);
				builder.setCt(ChangeType.DELETE);
			}
			builder.setData(JsonManager.me().getJson().toJson(cfg.toMap(DataModelKeyEnum.SOURCE)));
			listBuilder.addDatas(builder);
		}
		
		// 创建动态商品消息
		IMessage msg = MessageManager.me().create(StoreBO.reqDynamicCommodity, listBuilder.build().toByteArray());
		OnlinePlayerCache.sendMsgByOnlinePlayer(msg);
	}
	
	/**
	 * 接收商城信息
	 * @param storeInfo
	 */
	public void receiveStoreInfo(StoreInfo storeInfo){
		// 全服限购商品-购买记录
		ServerLimitCommodityBuyRecordCache.me().sync(storeInfo);
		Map<StoreCfg, Boolean> stores = Maps.newHashMap();
		Map<CommodityCfg, Boolean> commoditys = Maps.newHashMap();
		if (CollUtil.isNotEmpty(storeInfo.getUpdateStores())) {
			// 商店
			storeInfo.getUpdateStores().forEach((store)->{
				StoreCfg cfg = StoreCfgCache.me().getById(store.getId());
				if (cfg!=null) {
					boolean isNewDay = false;
					if (cfg.getLastRefreshDate() != null) {
						isNewDay = DateUtil.betweenDay(cfg.getLastRefreshDate(), store.getLastRefreshDate(), true) > 0;
					}
					cfg.setLastRefreshDate(store.getLastRefreshDate());
					cfg.setNextRefreshDate(store.getNextRefreshDate());
					stores.put(cfg, isNewDay);
				}
			});
		}
		
		if (CollUtil.isNotEmpty(storeInfo.getUpdateCommoditys())) {
			// 商品
			storeInfo.getUpdateCommoditys().forEach((commodity)->{
				CommodityCfg cfg = CommodityCfgCache.me().getById(commodity.getId());
				if (cfg!=null) {
					boolean isNewDay = false;
					if (cfg.getLastRefreshDate() != null) {
						isNewDay = DateUtil.betweenDay(cfg.getLastRefreshDate(), commodity.getLastRefreshDate(), true) > 0;
					}
					cfg.setLastRefreshDate(commodity.getLastRefreshDate());
					cfg.setNextRefreshDate(commodity.getNextRefreshDate());
					commoditys.put(cfg, isNewDay);
				}
			});
		}
		switch (storeInfo.getAction()) {
		case DEFAULT:
			break;
		case RESET:
			autoRefreshShop(stores, commoditys);
			break;
		}
	}
}
